---
title: 介绍
---

---

## 什么是 Riverpod?

Riverpod ([Provider](https://pub.dev/packages/provider) 的回文) 是 Flutter / Dart 平台的一个响应式缓存框架。它能自动获取、缓存、合并和计算网络请求，同时还会为你处理错误。

## 动机

现代的应用程序很少带有用户界面所需要的所有信息。一般来说，那些数据会从服务器异步获取。

但问题是，处理异步代码是比较困难的。虽然说 Flutter 本身提供了一些存储状态的方法，但除此之外，
它并没有其他额外的功能。因此，有许多问题仍然没有解决方案：

- 异步请求需要在本地缓存，因为只要 UI 刷新就重新执行请求的做法是不合理的。
- 由于缓存的存在，如果我们不小心可能会导致缓存过期。
- 我们也需要处理错误和加载中的各种状态。

大规模解决问题会比较困难，而且它们受到了许多功能的影响，比如：

- 下拉刷新
- 列表滚动加载
- 在键入时搜索
- 异步请求防抖
- 当不再需要时取消异步请求
- 积极的界面更新
- 离线模式
- ...

虽然实现这些功能很棘手，但这对一个良好的用户体验至关重要。
然而很少有其他包文件试图直接解决这些问题，而且大量的样板代码需要手工完成。

这就是 Riverpod 的由来。  
受 Flutter 组件的启发，Riverpod 尝试通过一种独特的方式来写业务逻辑，进而来解决这些问题。
对于状态来说，在许多方面 Riverpod 都可以类比于组件。

采用这种新的方式，上述复杂的功能大多都已默认被实现。你要做的只不过是关注 UI 实现。

不信？这里有一个例子。下面的代码片段是使用 Riverpod 的一个简化的 [Pub.dev](https://github.com/rrousselGit/riverpod/tree/master/examples/pub)
客户端应用。

```dart
// 从 pub.dev 获取包文件列表
@riverpod
Future<List<Package>> fetchPackages(
  FetchPackagesRef ref, {
  required int page,
  String search = '',
}) async {
  final dio = Dio();
  // 请求 API。这里我们用了 dio，当然你也可以使用任何其他的网络请求库。
  final response = await dio.get(
    'https://pub.dartlang.org/api/search?page=$page&q=${Uri.encodeQueryComponent(search)}',
  );

  // 将返回的 JSON 解码到 Dart 的对象。
  final json = response.data as List;
  return json.map(Package.fromJson).toList();
}
```

这段代码就是你要实现 “在键入时搜索” + “下拉刷新” + “无限列表” 功能所需的全部业务逻辑，同时还可以处理错误及加载中的状态。
